﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using DevelopTool.Common;
using DevelopTool.Model.Enums;
using Sunny.UI;

namespace DevelopTool.Forms.CommonControls.MarkdownEditor
{
    /// <summary>
    /// Markdown编辑器
    /// </summary>
    public partial class MarkdownEditorControl : UIUserControl
    {
        #region 公有属性
        /// <summary>
        /// 是否显示编辑器
        /// </summary>
        private bool showEditorControl = true;

        /// <summary>
        /// 是否显示编辑器
        /// </summary>
        [Description("是否显示编辑器")]
        [DefaultValue(value: true)]
        [Category("DevelopTool")]
        public bool ShowEditorControl
        {
            get
            {
                return this.showEditorControl;
            }
            set
            {
                this.showEditorControl = value;
                this.uiSplitContainer1.Panel1Collapsed = !value;
                this.btnSyncDocumentLocation.Visible = value;
            }
        }

        /// <summary>
        /// 是否显示代码高亮按钮
        /// </summary>
        private bool showCodeHighlightingBtn = true;

        /// <summary>
        /// 是否显示代码高亮按钮
        /// </summary>
        [Description("是否显示代码高亮按钮")]
        [DefaultValue(value: true)]
        [Category("DevelopTool")]
        public bool ShowCodeHighlightingBtn
        {
            get
            {
                return this.showCodeHighlightingBtn;
            }
            set
            {
                this.showCodeHighlightingBtn = value;
                this.btnCodeHighlighting.Visible = value;
            }
        }

        /// <summary>
        /// 编辑器默认占位文本
        /// </summary>
        private string editorControlDefaultText = $"{GlobalData.AppName_zh}Markdown编辑器实时预览";

        /// <summary>
        ///编辑器默认占位文本
        /// </summary>
        [Description("编辑器默认占位文本")]
        [DefaultValue(value: true)]
        [Category("DevelopTool")]
        public string EditorControlDefaultText
        {
            get
            {
                return this.editorControlDefaultText;
            }
            set
            {
                this.editorControlDefaultText = value;
            }
        }


        /// <summary>
        /// 文件路径或文件内容
        /// </summary>
        private string fileContent = "";

        /// <summary>
        /// 文件路径或文件内容
        /// </summary>
        public string FileContent
        {
            get
            {
                return this.fileContent;
            }
            set
            {
                this.fileContent = value;

                // if (isWebBrowserDocumentCompleted) this.codeEditorControl.ContentText = value;
                this.codeEditorControl.ContentText = value;
            }
        }


        #endregion 公有属性

        #region 事件

        public delegate void NeedChangeControlTitleHandler(string title);

        /// <summary>
        /// 需要改变窗口标题时触发的事件
        /// </summary>
        [Description("需要改变窗口标题时触发的事件"), Category("DevelopTool")]
        public event NeedChangeControlTitleHandler OnNeedChangeControlTitle;



        #endregion 事件

        #region 私有属性

        private bool isWebBrowserDocumentCompleted = false;

        #endregion 私有属性

        public MarkdownEditorControl()
        {
            InitializeComponent();
        }

        private void MarkdownEditorControl_Load(object sender, EventArgs e)
        {
            uiToolTip.SetToolTip(btnPrint, btnPrint.TipsText);
            uiToolTip.SetToolTip(btnOpenWithDefaultProgram, btnOpenWithDefaultProgram.TipsText);
            uiToolTip.SetToolTip(btnOpenInBrowser, btnOpenInBrowser.TipsText);
            uiToolTip.SetToolTip(btnCodeHighlighting, btnCodeHighlighting.TipsText);
            uiToolTip.SetToolTip(btnSyncDocumentLocation, btnSyncDocumentLocation.TipsText);

            if (this.showCodeHighlightingBtn)
                this.btnCodeHighlighting.Selected = Setting.Markdown.CodeHighlighting;

            this.btnSyncDocumentLocation.Selected = Setting.Markdown.SyncDocumentLocation;

            this.webBrowser.DocumentText = ThemHelper.SetHtmlThem(this.editorControlDefaultText, "Markdown编辑器");//webBrowser空内容占位，防止显示白屏

            this.codeEditorControl.ScrollChanged += this.CodeEditorControl_ScrollChanged;//代码编辑器滚动条滚动事件
        }



        private void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            // 拦截所有外部导航请求  
            if (!e.Url.AbsoluteUri.Contains("about:blank"))
            {
                Process.Start(e.Url.AbsoluteUri);//用系统默认的浏览器打开网址
                e.Cancel = true;
            }
        }


        /// <summary>
        /// 代码编辑器打开文件事件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileContent"></param>
        private void codeEditorControl_OnOpenFile(string filePath, string fileContent)
        {
            this.fileContent = filePath;
            this.Text = Path.GetFileName(filePath);
        }


        /// <summary>
        /// 编辑器内容改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void codeEditorControl_ContentTextChanged(object sender, EventArgs e)
        {
            ShowHtmlDocument(this.codeEditorControl.ContentText);
        }


        private void ShowHtmlDocument(string content)
        {
            string htmlTitle = string.Empty;
            ContentType contentType = MarkdownHelper.GetContentType(content);

            //简单识别markdown文件，如果是markdown格式化，否则直接展示到webBrowser
            if (contentType == ContentType.Markdown)
            {
                content = MarkdownHelper.MarkdownToHtml(content, this.btnCodeHighlighting.Selected);//Markdown内容转为HTML
            }
            else if (contentType == ContentType.FilePath)
            {
                this.codeEditorControl.ContentText = File.ReadAllText(content);
                content = MarkdownHelper.MarkdownFileToHtml(content, this.btnCodeHighlighting.Selected);//Markdown文件转为HTML                               
                htmlTitle = Path.GetFileName(fileContent);
            }
            content = ThemHelper.SetHtmlThem(content, htmlTitle);
            this.webBrowser.DocumentText = content;
        }

        /// <summary>
        /// 需要改变窗口标题时触发的事件
        /// </summary>
        /// <param name="title"></param>
        private void codeEditorControl_OnNeedChangeControlTitle(string title)
        {
            OnNeedChangeControlTitle?.Invoke(title);
        }


        private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(this.fileContent))
                {
                    this.webBrowser.DocumentText = ThemHelper.SetHtmlThem(this.editorControlDefaultText, "Markdown编辑器");
                }
                else
                {
                    this.ShowHtmlDocument(this.fileContent);
                }
            }
            catch
            {
                this.codeEditorControl.ContentText = this.fileContent;
            }

            webBrowser.DocumentCompleted -= webBrowser_DocumentCompleted;
            this.isWebBrowserDocumentCompleted = true;
        }


        /// <summary>
        /// 打印预览
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrint_Click(object sender, EventArgs e)
        {
            this.webBrowser.ShowPrintPreviewDialog();
        }



        /// <summary>
        /// 用默认程序打开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenWithDefaultProgram_Click(object sender, EventArgs e)
        {
            string filePath = string.Empty;

            string extension = "";

            //根据文件内容简单判断下文件类型，可能不准确
            ContentType contentType = MarkdownHelper.GetContentType(this.fileContent);

            if (contentType == ContentType.FilePath)//文件
            {
                filePath = this.fileContent;
            }
            else
            {
                if (contentType == ContentType.Markdown)//markdown文件
                {
                    extension = ".md";
                }
                else if (contentType == ContentType.HTML)//html文件
                {
                    extension = ".html";
                }
                else//未知文件类型
                {
                    extension = ".txt";
                }

                filePath = Path.Combine(DirectoryHelper.GetTempDirName(), $"{Path.GetFileNameWithoutExtension(this.Text)}{extension}");
                FileHelper.WriteFile(filePath, this.fileContent);
            }

            Process.Start(filePath);//用系统默认的程序打开
        }


        /// <summary>
        /// 用浏览器打开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenInBrowser_Click(object sender, EventArgs e)
        {
            //将内容保存到临时文件
            string content = this.codeEditorControl.ContentText;

            if (MarkdownHelper.GetContentType(this.fileContent) == ContentType.FilePath)//文件
            {
                content = MarkdownHelper.MarkdownFileToHtml(this.fileContent, this.btnCodeHighlighting.Selected, false);//Markdown转为HTML
                content = ThemHelper.SetHtmlThem(content, this.Text);
            }
            else
            {
                content = MarkdownHelper.MarkdownToHtml(this.fileContent, this.btnCodeHighlighting.Selected, false);//Markdown转为HTML
                content = ThemHelper.SetHtmlThem(content, this.Text);
            }

            string filePath = Path.Combine(DirectoryHelper.GetTempDirName(), $"{Path.GetFileNameWithoutExtension(this.Text)}.html");
            FileHelper.WriteFile(filePath, content);

            Process.Start(filePath);//用默认浏览器打开
        }


        /// <summary>
        /// 代码高亮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCodeHighlighting_Click(object sender, EventArgs e)
        {
            btnCodeHighlighting.Selected = !btnCodeHighlighting.Selected;

            Setting.Markdown.CodeHighlighting = this.btnCodeHighlighting.Selected;

            ShowHtmlDocument(this.codeEditorControl.ContentText);

            if (this.btnCodeHighlighting.Selected)
                UIMessageTip.ShowOk(this.btnCodeHighlighting, "已选中代码高亮");

        }


        /// <summary>
        /// 同步文档位置选择
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSyncDocumentLocation_Click(object sender, EventArgs e)
        {
            btnSyncDocumentLocation.Selected = !btnSyncDocumentLocation.Selected;

            Setting.Markdown.SyncDocumentLocation = this.btnSyncDocumentLocation.Selected;

            if (this.btnCodeHighlighting.Selected)
                UIMessageTip.ShowOk(this.btnCodeHighlighting, "已选中同步文档位置（实验性）");
        }

        /// <summary>
        /// 编辑器滚动条滚动时触发事件，用于同步编辑器和浏览器的滚动条位置
        /// </summary>
        /// <param name="scrollHeight">滚动条高度</param>
        /// <param name="value">滚动条当前值</param>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CodeEditorControl_ScrollChanged(int scrollHeight, int value, object sender, ScrollEventArgs e)
        {
            if (!this.btnSyncDocumentLocation.Selected) return;

            // 获取WebBrowser的滚动条高度
            int webBrowserScrollHeight = webBrowser.Document.Body.ScrollRectangle.Height;

            // 计算滚动比例
            double scrollRatio = (double)value / scrollHeight;

            // 根据比例计算WebBrowser的滚动位置
            int webBrowserScrollValue = (int)(scrollRatio * webBrowserScrollHeight);

            SetWebBrowserScrollPosition(webBrowserScrollValue);
        }

        /// <summary>
        /// 设置Browser滚动条位置
        /// </summary>
        /// <param name="y"></param>
        private void SetWebBrowserScrollPosition(int y)
        {
            if (webBrowser.Document != null)
            {
                string script = $"window.scrollTo(0, {y});";
                webBrowser.Document.InvokeScript("eval", new object[] { script });
            }
        }
    }
}
